../.
SEAC10
MTCT10 - TEDA11
  • Module MTCT10 TEDA11
  • stupunten 2
  • doelstelling
    Compressie gebruiken en toepassen in een multibound connected wereld
  • oplevering:
    Verslag

    dynamische media ripper / encoder

    met de hoeveelheid aan devices, bestandsformaten en andere die tegenwoordig bestaan is het moeilijk een 'good-for-all' manier te vinden om je media op te slaan, je weet namelijk nooit wat de dag van morgen voor eisen zal stellen en op welk device je het za gaan afspelen

    Tegenwoordig zijn de PDA's krachtig genoeg voor indrukwekkende media stunts te vertonen echter het schermoppervlak en opslagruimte zijn stukken minder als een desktop computer of tv-set-top-box. Een manier van on the fly omrenderen van media naargelang de nood er is kan in zo'n geval een oplossing bieden, stel je hierbij een pc voor die volledig dedicated is aan het weergeven, opslaan, omrenderen en catalogiseren van media; grote harddrive, genoeg rekencapaciteit, ethernet en evt. een beamer of groot scherm.

    zover niks bijzonders, de meesten onder ons zullen wel zo'n pc in huis hebben; tjokvol backups van legaal aangeschafte DVD's natuurlijk.

    Het bijzondere aan deze machine gaan de programmaatjes zijn die op de achtergrond de CD speler pollen om te kijken of er nieuwe media in voorradig ligt, langs zn opslagmedia loopt om de index up 2 date te houden, en de http frontend die clients afvangt onderweg naar hun media

    Clients kunnen connecten op enkele manieren:

  • netbios (Windows file sharing / samba)
  • http
  • via http wordt het clientplatform vrij dynamisch afgelezen, hier bestaan de normale webdeveloper trucjes voor die ik hieronder zal beschrijven

    onderdelen

    Een dergerlijke render-, file-, en application-server moet bestaan uit redelijk wat onderdelen, ik geef dan ook een opsomming van alle software waar een stuk 'film' doorheengaat vanaf het dvd-doosje tot de client pc / pda / mediaspeler
    1. dvd-doosje
    2. mediadetector
    3. dvdripper
    4. media encoder
    5. indexer
    6. web-, file-server
    7. media encoder
    8. client pc

    Bovenstaande dingen dan ook liefst op een manier dat we niet aan een bepaald operating system of proprietary bestandsformaat vastzitten, elk onderdeel moet ook 'los' van mekaar kunnen werken, maw met voor elk programmaatje een dedicated server. We zoeken naar oplossingen die op de 3 meest voorkomende platforms van dit moment (windows, linux, macintosh) beschikbaar zijn en waarbij dat er tussen deze versies weinig merkbaar verschil zit; dit geeft meestal aan dat voor elk platform waarschijnlijk dezelfde codebase gebruikt is. Die portability is belangrijk zodat als er in de toekomst op een nieuw systeem overgeschakeld wordt (GNU/Hurd) er zonder al teveel moeite kan overgeschakeld worden. Een goed voorbeeld van software waar dit niet het geval is is bijv. Internet Explorer 5. Als je de verschillen bekijkt in functionaliteit, ondersteuning van css, javascript, look 'n feel, footprint en nog vele andere dingen vraag je je af waarom twee overduidelijk andere programma's dezelfde naam dragen, maar ik dwaal af.

    Ik zet bovenstaande punten nogmaals onder elkaar en bespreek de gekozen software oplossingen.

    1. cddoosje

      waar het allemaal begint.
    2. mediadetector

      om te kijken of er een dvd in de drive ligt hebben we op elk platform genoeg aan een scriptje in respectievelijk cmd, bash en applescript om te pollen naar de aanwezigheid van nieuwe cd's
    3. dvdripper

      gelukkig dat het programma wat we gaan gebruiken voor te encoden ook dvd's aankan. Hieronder meer details in het hoodstuk 'the joys of mplayer' over dit prima stukje software
    4. media encoder

      wederom mplayer / mencoder
    5. indexer

      ook een scriptje in cmd/bash/applescript dat regelmatig wordt uitgevoerd, de harde schijven langsloopt en kijkt of de database in sync is met het filesystem en waar nodig bijwerkt.
    6. web / file server

      apache; samba, proftpd, of de standaard IIS/netbios combinatie op windows. Om de ftp/samba interface mogelijk te maken gebruiken we hier Lufs (linux userspace file system). op windows zou dit kunnen gebeuren met behulp van vfs.h, echter het prijskaartje van deze header file + licence bij microsoft is zo hoog dat ik hier geen test mee heb kunnen opzetten.
    7. mediaencoder

      wederom mplayer die hier omrenderd naar het gevraagde media formaat/ encoding/ afmeting.
    8. client pc

      vast mediaplayer, quicktime of mplayer

    Software - Details

    the joys of mplayer

    Mplayer is een frontend naar verschillende media libraries en kan van en naar elke bestandsformaat renderen wat hij kan afspelen , .. door de open structuur worden er steeds meer mediaformaten in dit programma ondersteund. Bij mplayer zit er ook mencoder die de encoding doet naar en van al die bestandsformaten. Verder kan dit versatile stukje software DVD's afspelen, snapt het TV kaarten en kan je de bitrate, geluidskwaliteit ea haarfijn instellen voor elk specifiek doel.

    web / fileserver

    elke server kan volstaan, apache / samba genieten mijn persoonlijke voorkeur wegens de grote mate van aanpasbaarheid die deze programma's hebben, maar in deze toepassing zullen de deamons enkel files moeten doorblazen zonder al te veel toeters of bellen. IIS, netscape, apache, omnihttpd, thttpd,.... op zich zijn ze er allemaal voor geschikt omdat de werkelijke interface zich op filesystem niveau zal bevinden.

    virtual file system

    Een filesystem als interface gebruiken kan je tot erg transparante solutions komen. omdat je een filesystem 'bent' werken alle top level programma's automatisch ook met die interface, hierdoor is het mogelijk een willekeurig ander protocol de media encoding functionaliteit mee te geven door simpelweg de virtual file root te 'sharen' via die service.
    Op macOS en Linux is dit vrij makkelijk te bewerkstelligen via userland filesystems, spijtig genoeg heb ik als platform win32 gekozen en zijn de headerfiles om dit soort trucjes op microsofts OS te doen extreem duur.

    Implementatie

    media detector

    Zoals eerder vermeld zal het eerste stukje van ons mediasysteem uit een simpel shellscriptje bestaan. Naargelang het platform / configuratie van de machine kan dit op enkele manieren gebeuren. Ik ga het volledige systeem op een windows bak bouwen met in het achterhoofd dat functionaliteit makkelijk geport moet kunnen worden naar een ander platform.

    Communiceren met de Windows API kan sinds WMI met scripting talen gebeuren
    Voor die tijd kon dat eigenlijk niet of je moest het op vieze manieren, zoals uitshellen naar rundll.exe , doen. Tegenwoordig kan dus dus gelukkig rechtstreeks. We maken een scriptje dat om de paar minuten langs de cdromdrives loopt en kijkt of er (nieuwe) media beschikbaar is; dit kan vrij strateforward in enkele regels VB-, of JScript
    De meest nette manier om dit te doen is een EventHandler in het systeem te hangen die op MediaInsertion geactiveerd wordt. Echter om op elk platform een uniforme aanpak te hebben opteer ik voor een loopje, dit is op elk platform mogelijk en zou zelfs in batch scripting gedaan kunnen worden. Echter omdat DVD's op een andere manier behandeld zulloen moeten worden als VCD's ben ik blij dit via WMI te kunnen doen en rechtstreeks alle benodigde informatie van de cdrom af te kunnen lezen. In het script wordt de variabele runCommand gedefinieerd; de waarde van deze variabele is het programma dat zal gerund worden als er nieuwe media detected is

    runCommand krijgt 4 argumenten mee bij execute;

  • Drive -- de driveletter (d:, e:, f:....)
  • MediaType -- is het een CDRW DVD CDROM....
  • VolumeSerialNumber -- de cd-serial
  • VolumeName -- de titel van de cd
  • runCommand is gedefinieerd als ripcd.bat; Als er bijvoorbeeld een CDRom ingestoken wordt in cddrive D: met volumenaam "Coole filmpjes" en het serienummer "1B1A83CC" zal het commando dat uitgevoerd wordt hetvolgende zijn:
    ripcd.bat "D:" "CD-ROM" "1B1A83CC" "Coole filmpjes"

    mediadetector.vbs
    1 rem mediadetector.vbs polling cdrom deamon for Windows 2000` 2 rem Windows Scripting >= 5.6 required 3 rem ©2004 GPL Matthijs Dalhuijsen -- http://thijs.dalhuijsen.com 4 on error resume next 5 6 Const TIMEOUT = 6000 'milliseconds! 7 runCommand="ripcd.bat" 8 targetPC="." 9 10 set oWMI = GetObject("winmgmts:\\" & targetPC & "\root\cimv2") 11 set cdroms = oWMI.ExecQuery("Select * from Win32_CDROMDrive") 12 set curVolumes = CreateObject("Scripting.Dictionary") 13 set eShell = CreateObject("WScript.Shell") 14 15 if cdroms.Count = 0 then 16 WScript.Echo "No CDROMDrive Detected on System", CrNlLf 17 WScript.Quit 18 end if 19 20 do while 1 21 set cdroms = oWMI.ExecQuery("Select * from Win32_CDROMDrive") 22 for each drive in cdroms 23 if drive.MediaLoaded then 24 if curVolumes.Exists(drive.Drive) then 25 if not curVolumes.Item(drive.Drive) = drive.VolumeSerialNumber & _ 26 "_" & drive.VolumeName then 27 curVolumes.add drive.Drive, drive.VolumeSerialNumber & _ 28 "_" & drive.VolumeName 29 set ans = eShell.Exec( runCommand & _ 30 " """ & drive.Drive & """ " & _ 31 """" & drive.MediaType & """ " & _ 32 """" & drive.VolumeSerialNumber & """ " & _ 33 """" & drive.VolumeName & """ " ) 34 end if 35 else 36 curVolumes.add drive.Drive, drive.VolumeSerialNumber & _ 37 "_" & drive.VolumeName 38 set ans = eShell.Exec( runCommand & _ 39 " """ & drive.Drive & """ " & _ 40 """" & drive.MediaType & """ " & _ 41 """" & drive.VolumeSerialNumber & """ " & _ 42 """" & drive.VolumeName & """ " ) 43 end if 44 end if 45 next 46 WScript.Sleep TIMEOUT 47 loop
    Stap ÈÈn van de cdripper is klaar; op naar nr 2: ripcd.bat

    ripcd.bat

    Ripcd is wederom een shellscriptje, ditmaal echter eentje die andere systembinaries aanspreekt voor zijn functie te vervullen; nadat gedetecteerd is dat er een 'nieuwe' cd in de machine zit moet er beslist worden wat voor actie er ondernomen wordt; als het mediatype DVD is moet er op een andere manier mee omgesporgen worden dan bij een CD-RW bijvoorbeeld. Handig kan zijn om in deze stap ook een 'backup' subje in het script te hangen zodat indien het geen mediacd is er iets interessants met de data kan gebeuren.
    Op dit moment echter is de mediaripping functionaliteit het enige wat belangerijk is.
    De voornaamste functies die ripcd zal moeten doen zijn:
  • controleer of aangeboden media al in de database is opgenomen of niet
  • indien media type DVD is rip 'm naar het basis encoding formaat en sla gegevens op in de database
  • indien media type CDROM of vergelijkbaar is loop recursive langs de bestanden en doet hetzelfde voor elke file waarvan de extensie gewild is.
  •       1 @echo off
          2 ::: ripcd.bat run actions on inserted new media
          3 ::: ©2004 GPL Matthijs Dalhuijsen -- http://thijs.dalhuijsen.com
          4 goto MAIN
          5 :USAGE
          6 echo Usage: %0 "Drive" "Type" "Serial" "Title"
          7 echo eg %0  "D:" "CD-ROM" "1B1A83CC"  "Coole filmpjes"
          8 :MAIN
          9 set MOPS="-ovc xvid -oac ac3"
         10 set STORAGE="C:\STORE\"
         11 set MENCODER="%ProgramFiles%.\mplayer\mencoder.exe"
         12 :CHKSTOR
         13 if exist %STORAGE% goto :CHKXST
         14 goto ERR_NOSTORE
         15 :CHKXST
         16 if exist %STORAGE%.\%3 goto :XSTINDB
         17 goto ALLGO
         18 :ALLGO
         19 set TODIR=%STORAGE%.\%3
         20 echo "%1" "%2" "%3" "%4" "%5"  "%6" "%7" "%8" "%9" > %TODIR%.\metadata.txt
         21 if "%2" == "DVD" goto RIPDVD
         22 goto RIPCD
         23 goto END
         24 :RIPDVD
         25 for %%a in (1 2 3 4 5 6 7 8 9 10 11 12) do %MENCODER% dvd://%%a %MOPS% -o %TODIR%.\%%a.avi
         26 goto END
         27 :RIPCD
         28 if exist %TODIR%.\manifest.txt del %TODIR%.\manifest.txt
         29 for %%a in (.avi .mpg .mov) do @dir /b/s %1\ | find /I "%%a" >> %TODIR%.\manifest.txt
         30 for /f "tokens=1 delims=^M" %%a in ('type %TODIR%.\manifest.txt') 
     do %MENCODER% "%%a" %MOPS% -o %TODIR%.\%%a.avi
         31 goto END
         32 :XSTINDB
         33 echo Entry %3 already exists!
         34 ::: if you want to overwrite directories change END to ALLGO on next line
         35 goto END
         36 :: 
         37 
         38 :ERR_NOSTORE
         39 echo No Store! %STORAGE%
         40 goto END
         41 ::
         42 :END
         43 ::
    
    op regel 16 wordt met if exist %STORAGE%.\%3 goto :XSTINDB gekeken of de file al geripd is of niet
    regel 29 worden alle files met gewenste files in een textbestand opgeslagen waarna op regel 30 alle filenames in dit textbestandje worden geript en opgeslagen
    op diezelfde regel 29 kan je de extensies toevoegen waar het scriptje naar zoekt. dit had evt. ook met for %%a in (.avi .mpg .mov) do dir *.%%a /s /b >> manifest.txt gekund
    opgelet: de ^M op regel 30 dient vervangen te worden door een letterlijke newline, in edit.exe kan je dit doen door eerst ^P te typen en dan enter

    Taking care of the clients

    Clients kunnen op 2 manieren aan files komen van de server. De voorkeur heeft het om op het intranet naar de VCD bak te connecten met je browser. De interface laat dan intranet urls ipv echte urls zien ( \\HOST\share\file.avi ipv http://HOST/share/file.avi )

    De webinterface herkent client devices op enkele manieren en past de default settings aan naar de connected client, op dat moment begint pas de file gegenereerd te worden die uiteindelijk bekeken wordt. De file houdt de gegenereerde file vast in de buffer tot er diskspace nodig is, vanaf dat dat gebeurt wordt de laatst bekekene file het eerst gedelete, het kan dus zijn dat er een file slechts ÈÈn keer gegenereerd wordt en nooit verwijderd als hij populair genoeg is.

    ClientDetectie

    The usual bag of browsertricks

    We gaan onderzscheid maken tussen een paar verschillende categorien van clients;
  • PDA's hebben gebrek aan 2 dingen: storage mogenlijkheid en schermoppervlakte. Encoding optie nummer ÈÈn is een file met kleine afmetingen, mono geluid, maar met niet al te zware compressie: Low power consumptie betekend vooral dat je de processor met rust moet laten
  • Smallband gebruikers lijken bijna op PDA's in resulterende file; echter mag hier de compressie volledig open worden geschroeft; zoveel mogelijk beeld /geluid voor zo min mogelijk Kb's.
  • Breedband gebruikers krijgen waarschijnlijk de meest populaire manier van encoden: 300kbps aan 320x240; mooi fullscreen te bekijken met stereo geluid
  • LAN-Gebruikers; De beste kwaliteit, gestreamed vanaf de fileserver; praktisch geen beperkingen aan formaat nog bandbreedte; Deze gebruikers krijgen een ÈÈn op ÈÈn kopie van de file voorgeschoteld
  • LAN gebruikers krijgen niet gewoon de originele file voorgeschoteld omdat het systeem op dezelfde manier met alle clients wilt omspringen; op deze manier kunnen er makkelijk uitbreidingen zoals plugins of authenticatie modules in het systeem ingepast worden zodat deze bij alle clients gedefinieerd worden

    Detectie Punten

    Om deze categorieÎn er uit te filteren en detecteren hebben we op de server de volgende detecteerbare punten tot onze beschikking:
  • Enviroment Vartiabelen:
    een van de weinige tools voor detectie waar je geen gebruik maakt van javascript zijn enviroment variabelen: Vooral de variablen die de client (browser) meestuurt met een request naar de server kan je gebruiken.
    In eertste instantie heb je USER_AGENT waarin de browser zijn eigen naam opslaat
    Natuurlijk is UA matching evil. Browsers liegen zo vaak over wie ze zijn. Echter omdat we enkel proberen opm de default instellingen van ons necoding programmatje goed te krijgen is dit niet zo'n probleem
    Windows CE based PDA's sturen buiten de gebruikelijke browserstrings nog enkele extra variabelen door die erg handig zijn voor ons voor 2 reden: De variable UA-pixels wordt op eerste request door de browser meegestuurd: We weten nu dat het een PDA is die connect + de afmetingen van het connected platform. Dat PDA's dit doen is niet toevallig; op deze manier is het voor een applicatie nog voor de eerste 'klik' mogelijk output aan te passen aan het connected platform iets wat aan 1 euro per Mb zeker geapreccieerd zal worden
  • Bandbeedte checken kan op 2 manieren gebeuren, jammer genoeg nooit zonder 'hulp' van de client. We is het mogelijk (gelukkig) dit zonder javascript te doen; indien de Browser meta http-equiv headers ondersteund tenminste. Het principe is in beide gevallen hetzelfde; je laat de browser een pagina binnenladen van gekende grootte en registreerd hoe lang deze erover deed deze binnen te halen
  • Het connected netwerk vormt een derde manier van detectie, dit dient dan vooral de LAN users die waarschijnlijk steeds via hetzelfde VLAN connecten en dus herkenbaar zijn aan hun IP
  • Een laatste manier van detectie zal authenticatie vormen. Een geregistreerde gebruiker zal waarschijnlijk zijn eigen favourite setting hebben en dus die voorgeschoteld krijgen
  • Detectie -- Implementatie

    Detectie is zo'n straightforward onderwerp dat ik niet al te lang bij deze code ga blijven stilstaan. de .txt linkjes geven steeds de source weer

  • Useragent matchen ua.pl
    ua.pl.txt
  • Snelheidsdetectie
    Detectie wordt in 2 beurten gedaan, eerst wordt een pagina met redelijk wat random ascii naar de browser verstuurd met daarin de tijd van versturen en de instructie de volgende detect pagina in te laden. Als dit ophalen van de volgende pagina te lang duurt stopt hier de detectie. Anders wordt er hierna een pagina van 750kb gegenereerd en wederom verstuurd en opgehaald. hiermee wordt dan getimed hoeveel de gebruiker aan bandbreedte heeft. Een correcte werkig van http-equiv meta tags is hierbij wel vereist.
    test de werking hier; detect0.pl en check hier de sources:
    detect0.pl.txt
    detect1.pl.txt
    detect2.pl.txt
  • Netwerkdetectie
    Netwerkdetectie kan vrij makkelijk door het connected ip adres te splitten op "." en te kijken of de eerste 2 nummers kloppen met het gevraagde subnet. Normaal gezien heb je problemen met IP's te gebruiken en moet je bijvoorbeeld kijken naar de (gemakkelijk te spoofen) X-Forwarded-For http header. In dit geval zijn we enkel geintresseerd ofdat de connectie van het locale netwerk komt en is een vrij eenvoudige oplossingen als dit al voldoende:
    #!/usr/bin/perl
    # localnet.pl detects if connected user comes from right network
    my ($first, $second, undef, undef) = split(/\./,$ENV{REMOTE_ADDR});
    if ($first == 192 && $second == 168) {
      print "Location: intranet.html\n\n";
    } else {
      print "Location: internet.html\n\n";
    }
    
  • Authenticatie
    Is voor de hand liggend maar is dependant op het gekozen authenticatie mechanisme
    bij standaard http authenticatie op apache bijvoorbeeld:
    perl: defined $ENV{REMOTE_USER} && print "Location: authenticated.html\n\n";
    php: if (isset($_SERVER[REMOTE_USER])) { Header("Location: authenticated.html\n\n") }
  • De laatste loodjes

    De data staat geript klaar op het filesystem, de connected client is bekend, wat rest is het renderen van de file en de client een url te verschaffen.
    Dit laatste (url verschaffen) is snel genoeg gedaan: er moet enkel even gekeken worden of het file://HOSTNAME/share/SERIENR/file.avi of http://HOSTNAME/share/SERIENR/file.avi moet zijn. maw iets als:
    printf "%s://%s/%s/%s", ($localnet ? "file" : "http"), $ENV{SERVER_NAME}, $share, $reqfile;

    last but not least: het omrenderen van de file op maat; hier kan je op zich alles instoppen wat mencoder kan, maar in de meeste gevallen zal enkel beeldformaat en kbps van belang zijn. als voorbeeld het scriptje wat voor PDA's geactiveerd wordt:
    pda.bat:

         1 @echo off
         2 ::: pda.bat custom encoding for pdas
         3 ::: ©2004 GPL Matthijs Dalhuijsen -- http://thijs.dalhuijsen.com
         4 ::: Usage: %0 c:\path\to\infile.avi c:\path\to\outfile.avi
         5 mencoder -oac copy -ovc copy -vop scal=160x120 "%1" -o "%2" > NUL 
    

    Uiteindelijk de client pc

    Omdat de c:\path\to\outfile hierboven bekend is is het nu maar een kwestie van deze in de vorm van een bereikbare url aan de client pc aan te geven. Dit kan zelfs rechtstreeks gebeuren zonder enige andere tussenklik. 2 dingen waar op gelet moet worden is de file-extensie en een correcte mime-type zodat de juiste player wordt geopend. De file extensie is vooral voor enkele windows versies van belang, maar gelukkig kan een querystring trucje hier soms uitweg bieden.
    bijvoorbeeld:
    /cgi-bin/dynamische_avi.pl?id=002314&iesux=thecorrectname.avi
    
    waardan in dynamische_avi.pl de juiste Content-Type: header wordt meegestuurd, bijvoorbeeld voor avi;
    print "Content-Type: video/x-msvideo\n\n";
    

     

     

    referenties

    http://www.webstandards.org/buzz/archive/2002_12.html#a000123
    http://www.microsoft.com/resources/documentation/windows/2000/server/scriptguide/en-us/default.mspx
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/detecting_media_insertion_or_removal.asp
    http://www.mplayerhq.hu/DOCS/man/en/manpage.txt
    http://www.robvanderwoude.com/robnavbat.html
    JAVP31
    HCIK10 - LING11
    FULO01
    FOTO10
    CCP411 - CCP421
    ANIM31